package com.easy.common.util;

import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class BeanUtil {

	public static List<String> getFields(Object o) {
        Class<?> clazz = o.getClass();
		List<String> list = new ArrayList<String>();

        while (true) {
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                String name = field.getName();

                Method method = null;
                try {
                   method = clazz.getMethod(getMethodName("get", name));
                } catch (NoSuchMethodException e) {
                  //  e.printStackTrace();
                }

                if (method != null && !Modifier.isStatic(field.getModifiers())) {
                    list.add(name);
                }
            }

            String name = clazz.getSimpleName();
            if ("EObject".equals(name) || "Object".equals(name)) {
                break;
            } else {
                clazz = clazz.getSuperclass();
            }
        }

		return list;
	}

	public static <T> String[] getFieldValues(Object o, List<String> fields) {
		if (fields != null) {
			String[] values = new String[fields.size()];
			int i = 0;

			for (String f : fields) {
				values[i++] = invokeGet(o, f);
			}
			
			return values;
		}

		return new String[0];
	}

    public static <T> T getBean(Map<String, String> map, Class<T> clazz) {
        Field[] fields = clazz.getDeclaredFields();
        T t = null;
        try {
            t = clazz.newInstance();

            if (fields != null) {
                for (Field field : fields) {
                    String name = field.getName();
                    String value = map.get(name);

                    invokeSet(t, name, value);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return t;
    }

    @SuppressWarnings("rawtypes")
	public static Class getGenericType(Object o, int index) {
        Type genType = o.getClass().getGenericSuperclass();
        if (!(genType instanceof ParameterizedType)) {
            return Object.class;
        }
        Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
        if (index >= params.length || index < 0) {
            throw new RuntimeException("Index outof bounds");
        }

        if (!(params[index] instanceof Class)) {
            return Object.class;
        }

        return (Class) params[index];
    }

	public static <T> String invokeGet(T t, String field) {
		Method method = null;
		Object value = null;
		try {
			method = t.getClass().getMethod(getMethodName("get", field));

			if (method != null) {
				value = method.invoke(t);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		if (value != null) {
			return value.toString();
		}

		return "";
	}

    public static <T> void invokeSet(T t, String field, String value) {
        Method method = null;
        try {
            method = t.getClass().getMethod(getMethodName("set", field),
                    String.class);

            if (method != null && value != null) {
                method.invoke(t, value);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

	private static String getMethodName(String suffix, String fieldName) {
		return suffix + fieldName.toUpperCase().substring(0, 1)
				+ fieldName.substring(1);
	}
}
